package heima_juc.test;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

/**
 * Java多线程实现的方式有四种
 * <p>
 * 1.继承Thread类，重写run方法
 * 2.实现Runnable接口，重写run方法，实现Runnable接口的实现类的实例对象作为Thread构造函数的target
 * 3.通过Callable和FutureTask创建线程
 * 4.通过线程池创建线程
 * <p>
 * 前面两种可以归结为一类：无返回值，原因很简单，通过重写run方法，run方式的返回值是void，所以没有办法返回结果。
 * 后面两种可以归结成一类：有返回值，通过Callable接口，就要实现call方法，这个方法的返回值是Object，所以返回的结果可以放在Object对象中。
 */
@Slf4j(topic = "c.CreateThread4Method")
public class CreateThread4Method {

    public static void main(String[] args) {
        log.debug("main running");

        thread1();
        thread2();
        thread3();
    }

    // 3. 实现线程的第三种方法，通过Callable和FutureTask创建线程
    private static void thread3() {
        FutureTask<String> futureTask = new FutureTask<>(new Callable<String>() {
            @Override
            public String call() throws Exception {
                log.debug("创建线程的第三种方式：通过Callable和FutureTask创建线程");
                return "xxx";
            }
        });
        Thread thread3 = new Thread(futureTask, "t3");
        thread3.start();

        try {
            System.out.println(futureTask.get());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }

    // 2 实现线程的第二种方法，实现Runnable接口，重新Runnable接口中的run方法，并把Runnable接口的实现类的实例对象作为Thread类的构造函数的参数
    private static void thread2() {
        Thread thread2_1 = new Thread(new Runnable() {
            @Override
            public void run() {

                log.debug("创建线程的第二种方式：实现Runnable接口的");
            }
        }, "t2_1");
        thread2_1.start();

        // lambda表达式写法
        Thread thread2_2 = new Thread(() -> log.debug("创建线程的第二种方式：实现Runnable接口的,匿名内部类的方式"), "t2_2");
        thread2_2.start();
    }

    // 1. 实现线程的第一种方式，继承Thread类，重写Thread类中的run方法，在run方法中写需要执行的任务代码
    private static void thread1() {
        Thread thread1 = new Thread("t1") {
            @Override
            public void run() {
                log.debug("创建线程的第一种方式：继承Thread类");
            }
        };
        thread1.start();
    }
}
